package org.erepublik.company.service;

import java.io.IOException;
import java.util.HashMap;

import org.cyberneko.html.parsers.DOMParser;
import org.erepublik.company.ECountry;
import org.erepublik.company.EProductType;
import org.erepublik.company.Tax;
import org.erepublik.company.Taxes;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

/**
 * Klasa odczytuje stawki podatkowe z internetu.
 * 
 * Robi to tylko raz, nastepnie zwraca skaszowane wyniki
 * 
 * @author Kacper Gorski 'Railman' railman85@gmail.com
 */
public class InternetVatService implements IVatService {

    private int DELAY = 5000;
    private HashMap<ECountry, Taxes> taxes = null;

    public HashMap<ECountry, Taxes> getVat() throws Exception {
        if (taxes != null)
            return taxes;

        HashMap<ECountry, Taxes> taxesMap = new HashMap<ECountry, Taxes>();
        ECountry[] countries = ECountry.values();
        for (ECountry country : countries) {
            Taxes tax = getTaxFromInternetPage(country);
            taxesMap.put(country, tax);
            Thread.sleep(DELAY);
        }

        taxes = taxesMap;
        return taxesMap;
    }

    private Taxes getTaxFromInternetPage(ECountry country) throws Exception {
        Taxes taxes = getTaxFromStream("http://www.erepublik.com/en/country/economy/" + country.getUrlName());
        taxes.setCountry(country);
        return taxes;
    }

    public Taxes getTaxFromStream(String url) throws SAXException, IOException {
        System.out.println("pobieram stawke podatku z " + url);
        DOMParser parser = new DOMParser();
        parser.parse(url);
        Document page = parser.getDocument();

        Taxes taxesObj = new Taxes();

        Node node = getTaxesTable(page);

        Node foodNode = node.getFirstChild().getNextSibling().getNextSibling().getNextSibling();
        Tax foodTax = nodeToTax(foodNode);
        Node ticketsNode = foodNode.getNextSibling().getNextSibling();
        Tax ticketTax = nodeToTax( ticketsNode );
        Node houseNode = ticketsNode.getNextSibling().getNextSibling();
        Tax houseTax = nodeToTax(houseNode);
        Node rifleNode = houseNode.getNextSibling().getNextSibling().getNextSibling().getNextSibling().getNextSibling().getNextSibling();
        Tax rifleTax = nodeToTax(rifleNode);
        Node tankNode = rifleNode.getNextSibling().getNextSibling();
        Tax tankTax = nodeToTax(tankNode);
        Node artilleryNode = tankNode.getNextSibling().getNextSibling();
        Tax artilleryTax = nodeToTax(artilleryNode);
        Node helicopterNode = artilleryNode.getNextSibling().getNextSibling();
        Tax helicopterTax = nodeToTax(helicopterNode);
        
        Node grainNode = helicopterNode.getNextSibling().getNextSibling();
        Tax grainTax = nodeToTax(grainNode);
        Node oilNode = grainNode.getNextSibling().getNextSibling();
        Tax oilTax = nodeToTax(oilNode);
        Node titaniumNode = oilNode.getNextSibling().getNextSibling();
        Tax titaniumTax = nodeToTax(titaniumNode);
        Node stoneNode = titaniumNode.getNextSibling().getNextSibling();
        Tax stoneTax = nodeToTax(stoneNode);
        Node ironNode = stoneNode.getNextSibling().getNextSibling();
        Tax ironTax = nodeToTax(ironNode);

        taxesObj.setTaxes(EProductType.FOOD, foodTax);
        taxesObj.setTaxes(EProductType.HOUSE, houseTax);
        taxesObj.setTaxes(EProductType.TICKET, ticketTax);
        taxesObj.setTaxes(EProductType.ARTILLERY,artilleryTax);
        taxesObj.setTaxes(EProductType.RIFLE, rifleTax);
        taxesObj.setTaxes(EProductType.TANK, tankTax);
        taxesObj.setTaxes(EProductType.HELICOPTER, helicopterTax);
        
        taxesObj.setTaxes(EProductType.IRON, ironTax);
        taxesObj.setTaxes(EProductType.TITANIUM, titaniumTax);
        taxesObj.setTaxes(EProductType.OIL, oilTax);
        taxesObj.setTaxes(EProductType.STONE, stoneTax);
        taxesObj.setTaxes(EProductType.GRAIN, grainTax);

        return taxesObj;
    }

    // zwraca czesc drzewa DOM, reprezentujacego tabele z podatkami
    private Node getTaxesTable(Node page) {
        Node node = page.getFirstChild();

        while (node != null) {

            if (node.getNodeName().equals("TABLE") && containsAttribute(node))
                return node;
            Node child = getTaxesTable(node);

            if (child != null)
                return child;
            node = node.getNextSibling();
        }

        return null;
    }

    private boolean containsAttribute(Node node) {
        return node.getAttributes().getNamedItem("class") != null
                && node.getAttributes().getNamedItem("class").getNodeValue().equals("citizens largepadded");
    }

    private Tax nodeToTax(Node node) {
	        int vat=0;
	        int importTax=0;
	        int incomeTax=0;
	        
	        node = node.getFirstChild().getNextSibling();
	        node = node.getNextSibling().getNextSibling();
	        node = node.getNextSibling().getNextSibling();
	        Node incomeTaxNode = node.getFirstChild().getFirstChild();
	        node = node.getNextSibling().getNextSibling();
	        incomeTax = Integer.parseInt(incomeTaxNode.getNodeValue());
	        Node importHouseTaxNode = node.getFirstChild().getFirstChild();
	        importTax = Integer.parseInt(importHouseTaxNode.getNodeValue());
	        node = node.getNextSibling().getNextSibling();
	        node = node.getFirstChild();
	        if (node.getNodeName().equals("#text"))
	            node = node.getNextSibling();
	        node = node.getFirstChild();

	        if (node==null)
	            vat = 0;
	        else
	            vat = Integer.parseInt(node.getNodeValue());

	        Tax tax = new Tax(vat, importTax, incomeTax);
	        return tax;
	}

}


